package cn.iocoder.yudao.module.shop.service.store;

import cn.iocoder.yudao.module.shop.enums.store.StoreBizTypeEnum;
import cn.iocoder.yudao.module.shop.service.storerecord.ShopStoreRecordService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.*;
import cn.iocoder.yudao.module.shop.controller.admin.store.vo.*;
import cn.iocoder.yudao.module.shop.dal.dataobject.store.StoreDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.shop.convert.store.StoreConvert;
import cn.iocoder.yudao.module.shop.dal.mysql.store.StoreMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.shop.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

/**
 * 库存 Service 实现类
 *
 * @author 曹建伟
 */
@Service
@Validated
public class StoreServiceImpl implements StoreService {

    @Resource
    private StoreMapper storeMapper;

    @Resource
    private ShopStoreRecordService shopStoreRecordService;

    @Override
    public Long createStore(StoreCreateReqVO createReqVO) {

        if(createReqVO.getCode() != null && createReqVO.getCode() != ""){
            StoreDO storeDO = storeMapper.selectByCode(createReqVO.getCode(), createReqVO.getTenantId());
            if(storeDO != null){
                throw exception(STORE_CODE_EXISTS);
            }
        }

        // 插入
        StoreDO store = StoreConvert.INSTANCE.convert(createReqVO);
        storeMapper.insert(store);

        //todo log
        String content = String.format(StoreBizTypeEnum.CREATE.getDescription(), store.getName(), store.getNum(), store.getNum());
        // 返回
        return store.getId();
    }

    @Override
    public void updateStore(StoreUpdateReqVO updateReqVO) {
        // 校验存在
        validateStoreExists(updateReqVO.getId());
        // 更新
        StoreDO updateObj = StoreConvert.INSTANCE.convert(updateReqVO);
        storeMapper.updateById(updateObj);
    }

    @Override
    public void deleteStore(Long id) {
        // 校验存在
        validateStoreExists(id);
        // 删除
        storeMapper.deleteById(id);
    }

    private void validateStoreExists(Long id) {
        if (storeMapper.selectById(id) == null) {
            throw exception(STORE_NOT_EXISTS);
        }
    }

    @Override
    public StoreDO getStore(Long id) {
        return storeMapper.selectById(id);
    }

    @Override
    public StoreDO getStoreByCode(String code, Long tenantId){
        return storeMapper.selectByCode(code, tenantId);
    }

    @Override
    public List<StoreDO> getStoreList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return storeMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<StoreDO> getStorePage(StorePageReqVO pageReqVO) {
        return storeMapper.selectPage(pageReqVO);
    }

    @Override
    public List<StoreDO> getStoreList(StoreExportReqVO exportReqVO) {
        return storeMapper.selectList(exportReqVO);
    }

    @Override
    public List<StoreDO> getAllList() {
        return storeMapper.selectList();
    }

    @Override
    public void outStore(StoreNumReqVO storeNumReqVO){
        validateStoreNum(storeNumReqVO);
        validateStoreExists(storeNumReqVO.getId());

        storeNumReqVO.setNum(-storeNumReqVO.getNum());

        StoreDO storeDO = getStore(storeNumReqVO.getId());
        StoreDO updateObj = StoreConvert.INSTANCE.convert(storeDO, storeNumReqVO);

        Integer marketPrice = storeDO.getMarketPrice() * storeNumReqVO.getNum();
        Integer costPrice = storeDO.getCostPrice() * storeNumReqVO.getNum();
        Integer changeNum = -storeNumReqVO.getNum();
        Integer beforeNum = storeDO.getNum();
        Integer leftNum = updateObj.getNum();
        String purpose = "出库";

        shopStoreRecordService.record(null, storeDO.getName(), marketPrice, costPrice, changeNum, storeDO.getUnit(), beforeNum, leftNum, purpose, storeDO.getTenantId(), 0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void outStore(StoreOutReqVO reqVO){
        for(int i = 0; i<reqVO.getItems().length; i++){
            StoreDO storeDO = getStore(reqVO.getItems()[i].getId());
            if(storeDO == null){
                throw exception(STORE_NOT_EXISTS);
            }

            Integer marketPrice = reqVO.getItems()[i].getMarketPrice();
            Integer costPrice = storeDO.getCostPrice() * reqVO.getItems()[i].getNum();
            Integer changeNum = -reqVO.getItems()[i].getNum();
            Integer beforeNum = storeDO.getNum();
            Integer leftNum = storeDO.getNum() + changeNum;

            shopStoreRecordService.record(null, storeDO.getName(), marketPrice, costPrice, changeNum, storeDO.getUnit(), beforeNum, leftNum, reqVO.getPurpose(), storeDO.getTenantId(), 0);
        }
    }

    @Override
    public void inStore(StoreNumReqVO storeNumReqVO){
        validateStoreNum(storeNumReqVO);
        validateStoreExists(storeNumReqVO.getId());

        StoreDO storeDO = getStore(storeNumReqVO.getId());
        StoreDO updateObj = StoreConvert.INSTANCE.convert(storeDO, storeNumReqVO);
        storeMapper.updateById(updateObj);

        Integer marketPrice = storeDO.getMarketPrice() * storeNumReqVO.getNum();
        Integer costPrice = storeDO.getCostPrice() * storeNumReqVO.getNum();
        Integer changeNum = storeNumReqVO.getNum();
        Integer beforeNum = storeDO.getNum();
        Integer leftNum = updateObj.getNum();
        String purpose = "入库";

        shopStoreRecordService.record(null, storeDO.getName(), marketPrice, costPrice, changeNum, storeDO.getUnit(), beforeNum, leftNum, purpose, storeDO.getTenantId(), 0);
    }

    @Override
    public void consume(Long id, Integer num, Integer typeId, Long tenantId, LocalDateTime time, String purpose) {
        validateStoreExists(id);
        StoreBizTypeEnum bizTypeEnum = StoreBizTypeEnum.getByType(typeId);
        StoreDO storeDO = getStore(id);
        StoreDO updateObj = StoreConvert.INSTANCE.convert(storeDO, -num);
        storeMapper.updateById(updateObj);

        Integer marketPrice = storeDO.getMarketPrice() * num;
        Integer costPrice = storeDO.getCostPrice() * num;
        Integer changeNum = -num;
        Integer beforeNum = storeDO.getNum();
        Integer leftNum = updateObj.getNum();

        shopStoreRecordService.record(time, storeDO.getName(), marketPrice, costPrice, changeNum, storeDO.getUnit(), beforeNum, leftNum, purpose, tenantId, 1);
    }

    private void validateStoreNum(StoreNumReqVO storeNumReqVO) {
        if(storeNumReqVO.getNum() < 0) {
            throw exception(STORE_NUM_ERROR);
        }
    }
}
